package com.example.wx.other;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class SnowIdUtils {
    public SnowIdUtils() {
    }

    public static long uniqueLong() {
        return SnowIdUtils.SnowFlake.SNOW_FLAKE.nextId();
    }

    public static String uniqueLongHex() {
        return String.format("%016x", uniqueLong());
    }

    private static class SnowFlake {
        private static final SnowFlake SNOW_FLAKE = new SnowFlake();
        private final long START_TIMESTAMP = 1557489395327L;
        private final long SEQUENCE_BIT = 12L;
        private final long MACHINE_BIT = 10L;
        private final long TIMESTAMP_LEFT = 22L;
        private final long MAX_SEQUENCE = 4095L;
        private final long MAX_MACHINE_ID = 1023L;
        private long machineIdPart;
        private long sequence = 0L;
        private long lastStamp = -1L;

        private SnowFlake() {
            int machine_id = 4321;

            try {
                InetAddress addr = InetAddress.getLocalHost();
                String localIp = addr.getHostAddress();
                Long ip_ = Long.parseLong(localIp.replaceAll("\\.", ""));
                machine_id = ip_.hashCode() % 128;
            } catch (UnknownHostException var5) {
                UnknownHostException e = var5;
                e.printStackTrace();
            }

            this.machineIdPart = ((long)machine_id & 1023L) << 12;
        }

        public synchronized long nextId() {
            long currentStamp = this.timeGen();
            if (currentStamp < this.lastStamp) {
                throw new BizException(String.format("时钟已经回拨.  Refusing to generate id for %d milliseconds", this.lastStamp - currentStamp));
            } else {
                if (currentStamp == this.lastStamp) {
                    this.sequence = this.sequence + 1L & 4095L;
                    if (this.sequence == 0L) {
                        currentStamp = this.getNextMill();
                    }
                } else {
                    this.sequence = 0L;
                }

                this.lastStamp = currentStamp;
                return currentStamp - 1557489395327L << 22 | this.machineIdPart | this.sequence;
            }
        }

        private long getNextMill() {
            long mill;
            for(mill = this.timeGen(); mill <= this.lastStamp; mill = this.timeGen()) {
            }

            return mill;
        }

        protected long timeGen() {
            return System.currentTimeMillis();
        }
    }
}